home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xnetbris.00 / xnetbris / client.c < prev    next >
C/C++ Source or Header  |  1995-07-23  |  9KB  |  346 lines

  1. /*
  2.    This is the network back-end for Netbrisk (the client program).
  3.     Copyright (C) 1995 Brendan Bartlett
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. /* The "protocol" for the server is as follows -
  21.  *  - a packet of type INFORM_TYPE telling the client the numplayers and play_type
  22.  * - a MOVE_TYPE packet, with the brisk card in the card.
  23.  *
  24.  * - 3 MOVE_TYPE packets, giving the client the cards in their hand
  25.  *
  26.  * after the beginning point, the game is fairly normal with
  27.  * - packets of MOVE_TYPE or MESSAGE_TYPE 
  28.  * - a very important packets of MOVE_EXPECTED tells the client that
  29.  *      a move is expected from them now, and the server is idling.
  30.  *
  31.  *
  32.  * the client can do whatever they want with these packets
  33.  * "Fabio" and Brendan Bartlett, 1995
  34. */
  35.  
  36. /* Arggg!
  37.  * For the servers convience, the graphics are a little screwed up
  38.  * the card->weight:
  39.  *      9           ace
  40.  *      8           three
  41.  *      7           king (re)
  42.  *      6           girl (donna)
  43.  *     .
  44.  *     .
  45.  *     .
  46. */
  47.  
  48.  
  49.  
  50. #include <stdio.h>
  51. #include <signal.h>
  52. #include <stdlib.h>
  53. #include <sys/types.h>
  54. #include <sys/time.h>
  55. #include <sys/socket.h>
  56. #include <netinet/in.h>
  57. #include <arpa/inet.h>
  58. #include <netdb.h>
  59. #include <unistd.h>
  60. #include <sys/types.h>
  61. #include <sys/uio.h>
  62.  
  63. #include "brisk.h"
  64.  
  65. int server_fd, numplayers, play_type, okmove, my_number;
  66.  
  67. char *errormsg;
  68.  
  69.  
  70. static struct card brisk;
  71. static struct card hand[3];                             /* This is an array with the current cards in this players hand */
  72.  
  73. void process_input(void);
  74.  
  75. extern void show_brisk(int, int);                 /* calls from here to front end */
  76. extern void show_card(int, int, int);
  77. extern void show_table(int, int, int);           /*       "             "        */
  78. extern void show_clear_table(char, char, int);
  79. extern void show_move_expected(int);
  80.  
  81. void open_server(char *, int);
  82. int  play_card(int);                               /* called from front-end */
  83. void ok_score(void);
  84.  
  85.  
  86. static int get_card(int);                                 /* reads a new card from the server */
  87. static int give_score(int, char *);
  88.  
  89. static void update_cards(void);             /* some sort of change to the hand -- tell the user */
  90.  
  91. int handler(int signum);
  92. int start_client(char * hostname, int port);
  93.  
  94.  
  95. int handler(int signum)
  96. {
  97.   fprintf(stderr, "got SIGPIPE, client cleaning..\n");
  98.   
  99.   close(server_fd);
  100.   exit(0);
  101. }
  102.  
  103. /* Tries to connect with the server given by 'hostn'
  104. */
  105. void open_server(char *hostn, int dport)
  106. {
  107.   int port = 10000;
  108.   struct packet p;
  109.   int i;
  110.  
  111.   signal(SIGPIPE, handler);
  112.   if(dport != 0)
  113.     port = dport;
  114.  
  115.   if(!start_client(hostn, port))
  116.     {
  117.       printf("cannot connect to server '%s'\n", hostn);
  118.       exit(0);
  119.     }
  120.  
  121.  
  122.   /* Read in our hand from the server */
  123.  
  124.   for(i = 0; i < 3; i++)
  125.     {
  126.       get_card(i);
  127.       show_card(i, hand[i].suit, hand[i].weight);
  128.     }
  129.  
  130.   /* Read in the brisk from the server */
  131.  
  132.   read(server_fd, &p, sizeof(struct packet));
  133.  
  134.   if(p.type != MOVE_TYPE || p.data.move.player != 5)
  135.     {
  136.       fprintf(stderr, "server did not send the brisk card!\n");
  137.       exit(0);
  138.     }
  139.   
  140.   memcpy(&brisk, &p.data.move.play_card, sizeof(struct card));
  141.  
  142.   show_brisk(brisk.suit, brisk.weight);
  143.  
  144. }
  145.  
  146. /*
  147.  * This routine will read from the server for a packet of MOVE_TYPE (or DEAL_TYPE) and will fill in the
  148.  * given card in the hand[] array.
  149.  *
  150.  * If the packet is of type DEAL_TYPE, the argument 'card' is ignored and the suggested value in the
  151.  * packet is used instead.
  152.  *
  153.  * Returns 0 on failure
  154.  *         1 on success 
  155.  */
  156. static int get_card(int card)
  157. {
  158.   struct packet p;
  159.   
  160.   read(server_fd, &p, sizeof(struct packet));
  161.  
  162.   if( (p.type != MOVE_TYPE) && (p.type != DEAL_TYPE) )
  163.     {
  164.       fprintf(stderr, "FATAL ERROR: MOVE_TYPE or DEAL_TYPE expected!\n");
  165.       return 0;
  166.     }
  167.  
  168.   if(p.type == DEAL_TYPE)
  169.     memcpy(&hand[p.data.deal.rec_place], &p.data.deal.deal_card, sizeof(struct card));
  170.   else
  171.     memcpy(&hand[card], &p.data.move.play_card, sizeof(struct card));
  172.  
  173.   return 1;
  174. }
  175.  
  176. void ok_score(void)
  177. {
  178.   struct packet out;
  179.  
  180.   out.type = OK;
  181.  
  182.   write(server_fd, &out, sizeof(struct packet));
  183. }
  184.  
  185. void process_input(void)
  186. {
  187.   struct packet in, out;
  188.   char buf[80];
  189.   int i;
  190.  
  191.  
  192.   read(server_fd, &in, sizeof(struct packet));
  193.  
  194.   switch(in.type)
  195.     {
  196.     case LAST_HAND:
  197.       show_brisk(-1, -1);         /* tell the front-end to erase the brisk card */
  198.       break;
  199.  
  200.     case END_GAME:
  201.       printf("That's the end of the game!\n");
  202.  
  203.       printf("Final Scores: %d for you, %d for the other %s\n",
  204.          give_score(0, in.data.score.scores),
  205.          give_score(1, in.data.score.scores), (play_type == CHAOS) ? "player" : "team");
  206.  
  207.       close(server_fd);
  208.       exit(0);
  209.  
  210.     case MESSAGE_TYPE:
  211.       printf("message: [%s]\n", in.data.message.string);
  212.       break;
  213.  
  214.     case MOVE_TYPE:
  215.       show_table(in.data.move.tablepos, in.data.move.play_card.suit, in.data.move.play_card.weight);
  216.  
  217.       break;
  218.     case SCORE_UPDATE:
  219.       
  220.       show_clear_table(give_score(0, in.data.score.scores),
  221.                give_score(1, in.data.score.scores), in.data.score.lastwin);
  222.     
  223.       break;
  224.  
  225.     case DEAL_TYPE:
  226.       memcpy(&hand[in.data.deal.rec_place], &in.data.deal.deal_card, sizeof(struct card));
  227.       show_card(in.data.deal.rec_place, hand[in.data.deal.rec_place].suit, hand[in.data.deal.rec_place].weight);
  228.  
  229.       break;
  230.     case INFORM_TYPE:
  231.       printf("server send INFORM_TYPE. Not at start of game\n");
  232.       break;
  233.     case MOVE_EXPECTED:
  234.       if(in.data.move.player == my_number)
  235.       okmove = 1;
  236.       
  237.       show_move_expected(in.data.move.player);
  238.     }
  239. }
  240. /*
  241.  * Given the packet 'p' return the score of 'who', where
  242.  * who is 0 for yourself and 1 for the other player/team
  243.  */
  244. static int give_score(int who, char *scores)
  245. {
  246.   char scoretab[] = { 0, 1, 0, 1 };
  247.  
  248.   if(who == 0)
  249.     return scores[scoretab[my_number]];
  250.   else
  251.     return scores[! scoretab[my_number]];
  252.  
  253. }
  254.  
  255. int play_card(int cardnum)
  256. {
  257.   struct packet out, in;
  258.  
  259.   if(!okmove)
  260.     {
  261.       errormsg = "It's not your turn!";
  262.       return 0;
  263.     }
  264.   
  265.   if(hand[cardnum].suit == -1 && hand[cardnum].weight == -1)
  266.     {
  267.       errormsg = "There's no card there!";
  268.       return 0;
  269.     }
  270.  
  271.   out.type = MOVE_TYPE;
  272.   out.data.move.player = my_number;
  273.  
  274.   out.data.move.play_card.suit = hand[cardnum].suit;
  275.   out.data.move.play_card.weight = hand[cardnum].weight;
  276.  
  277.   write(server_fd, &out, sizeof(struct packet));
  278.  
  279.   read(server_fd, &in, sizeof(struct packet));
  280.  
  281.   if(in.type != OK)
  282.     {
  283.       printf("Impossible: not OK in play_card [num %d]: %d %d\n", cardnum, hand[cardnum].suit, hand[cardnum].weight);
  284.       return 0;
  285.     }
  286.  
  287.   hand[in.data.ok.cardpos].suit = -1;
  288.   hand[in.data.ok.cardpos].weight = -1;
  289.   okmove = 0;
  290.  
  291.   return 1;
  292. }
  293.  
  294. int start_client(char *hostname, int port)
  295. {
  296.   struct sockaddr_in addr;
  297.   struct protoent *proto;
  298.   struct hostent *host;
  299.   struct packet p;
  300.  
  301.   proto = getprotobyname("tcp");
  302.   if(!proto)
  303.     {
  304.       printf("tcp not supported here.\n");
  305.       return 0;
  306.     }
  307.  
  308.   host = gethostbyname(hostname);
  309.  
  310.   if(!host)
  311.     {
  312.       printf("cannot find host '%s'\n", host);
  313.       return 0;
  314.     }
  315.  
  316.   addr.sin_family = AF_INET;
  317.   addr.sin_port = htons(port);
  318.   addr.sin_addr.s_addr = inet_addr(hostname);
  319.   memcpy((char *)&addr.sin_addr, (char *)(*host->h_addr_list), host->h_length);
  320.   server_fd = socket(PF_INET, SOCK_STREAM, proto->p_proto);
  321.   if(server_fd == -1)
  322.     {
  323.       perror("socket");
  324.       return 0;
  325.     }
  326.  
  327.   printf("Attemping to connect to port %i of server %s.\n", port, hostname);
  328.   
  329.   if(connect(server_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
  330.     {
  331.       perror("connect");
  332.       return 0;
  333.     }
  334.  
  335.   read(server_fd, &p, sizeof(struct packet));
  336.   
  337.   printf("# players %d, play_type %d.  I am player # %d\n", p.data.inform.numplayers, p.data.inform.play_type,
  338.      p.data.inform.yournumber);
  339.  
  340.   numplayers = p.data.inform.numplayers;
  341.   play_type = p.data.inform.play_type;
  342.   my_number = p.data.inform.yournumber;
  343.  
  344.   return 1;
  345. }
  346.